#include "third_area_manager.h"
#include <QHostAddress>
#include <QJsonObject>
#include <QRegularExpression>
#include "application/map/lift/lift_manager.h"

namespace application {
namespace third_area {

ThirdAreaManager::ThirdAreaManager(std::shared_ptr<kernel::ILogger> logger, QObject* parent)
    : QObject(parent)
    , m_logger(logger)
{
}

bool ThirdAreaManager::initConnection(quint16 port)
{
    if (m_server && m_server->isListening()) {
        return true;
    }

    if (m_server) {
        m_server->deleteLater();
        m_server = nullptr;
    }

    m_server = new infrastructure::io::HttpServer(this);

    if (!m_server->listen(QHostAddress::Any, port)) {
        if (m_logger) {
            m_logger->error(QString("第三方区域HTTP服务器启动失败: %1")
                .arg(m_server->errorString()));
        }
        m_server->deleteLater();
        m_server = nullptr;
        return false;
    }

    if (m_logger) {
        m_logger->info(QString("第三方区域HTTP服务器启动: 端口=%1").arg(port));
    }

    m_server->receive_callback = std::bind(&ThirdAreaManager::processPostData,
                                           this,
                                           std::placeholders::_1,
                                           std::placeholders::_2);
    return true;
}

void ThirdAreaManager::setLiftManager(std::weak_ptr<lift::LiftManager> liftManager)
{
    m_liftManager = liftManager;

    for (auto it = m_areaLiftBindings.constBegin(); it != m_areaLiftBindings.constEnd(); ++it) {
        const QString& areaId = it.key();
        if (auto area = m_areaHash.value(areaId, nullptr)) {
            area->configureLiftLockResource(it.value(), m_liftManager);
        }
    }
}

void ThirdAreaManager::addArea(const QString& areaId, int floor, int liftNum)
{
    if (m_areaHash.contains(areaId)) {
        if (m_logger) {
            m_logger->warning(QString("第三方区域已存在: %1").arg(areaId));
        }
        return;
    }

    ThirdBlockArea* area = new ThirdBlockArea(areaId, floor, m_logger, this);
    m_areaList.append(area);
    m_areaHash.insert(areaId, area);
    if (liftNum > 0) {
        m_areaLiftBindings.insert(areaId, liftNum);
        area->configureLiftLockResource(liftNum, m_liftManager);
    }

    if (m_logger) {
        m_logger->info(QString("添加第三方区域: ID=%1, 楼层=%2").arg(areaId).arg(floor));
    }
}

void ThirdAreaManager::removeArea(const QString& areaId)
{
    if (m_areaHash.contains(areaId)) {
        ThirdBlockArea* area = m_areaHash.take(areaId);
        m_areaList.removeOne(area);
        m_areaLiftBindings.remove(areaId);
        area->deleteLater();

        if (m_logger) {
            m_logger->info(QString("移除第三方区域: ID=%1").arg(areaId));
        }
    }
}

void ThirdAreaManager::connectArea(const QString& areaId, ThirdBlockArea* area)
{
    if (!m_areaHash.contains(areaId)) {
        m_areaHash.insert(areaId, area);
        if (!m_areaList.contains(area)) {
            m_areaList.append(area);
        }
    }

    if (area && m_areaLiftBindings.contains(areaId)) {
        area->configureLiftLockResource(m_areaLiftBindings.value(areaId), m_liftManager);
    }
}

ThirdBlockArea* ThirdAreaManager::getArea(const QString& areaId) const
{
    return m_areaHash.value(areaId, nullptr);
}

bool ThirdAreaManager::parseRequestString(const QString& srcString,
                                          QString& res,
                                          QString& action,
                                          QString& rid)
{
    QRegularExpression resRe("(?<=res=)(\\w+)");
    QRegularExpression actionRe("(?<=action=)(\\w+)");
    QRegularExpression ridRe("(?<=rid=)(\\w+)");

    QRegularExpressionMatch match = resRe.match(srcString);
    if (match.hasMatch()) {
        res = match.captured();
    } else {
        return false;
    }

    match = actionRe.match(srcString);
    if (match.hasMatch()) {
        action = match.captured();
    } else {
        return false;
    }

    match = ridRe.match(srcString);
    if (match.hasMatch()) {
        rid = match.captured();
    } else {
        return false;
    }

    return true;
}

void ThirdAreaManager::processPostData(QTcpSocket* socket, QString postData)
{
    if (m_logger) {
        m_logger->debug("�յ�������������������");
    }

    QString res, action, rid;
    bool parseSuccess = parseRequestString(postData, res, action, rid);

    QJsonObject rspObj;
    rspObj.insert("ok", QJsonValue(true));
    rspObj.insert("msg", QJsonValue("success"));

    if (!parseSuccess || !m_areaHash.contains(res)) {
        m_server->respondPost(socket, rspObj);
        return;
    }

    ThirdBlockArea* area = m_areaHash.value(res, nullptr);
    if (!area) {
        m_server->respondPost(socket, rspObj);
        return;
    }

    const bool hasLiftBinding = m_areaLiftBindings.contains(res);

    if (action == "hold") {
        if (!area->thirdPartyOccupy(rid)) {
            if (m_logger) {
                m_logger->warning(QString("����������ռ��ʧ��: ����=%1, ����=%2")
                    .arg(res).arg(rid));
            }
            rspObj.insert("ok", QJsonValue(false));
            rspObj.insert("msg", QJsonValue("Area occupied"));
            m_server->respondPost(socket, rspObj);
            return;
        }

        if (hasLiftBinding && !area->acquireLiftLock(rid)) {
            area->cancelOccupy(rid);
            rspObj.insert("ok", QJsonValue(false));
            rspObj.insert("msg", QJsonValue("Lift occupied"));
            m_server->respondPost(socket, rspObj);
            return;
        }

        emit areaOccupied(res, rid);
        m_server->respondPost(socket, rspObj);
        return;
    }

    if (action == "release") {
        if (m_logger) {
            m_logger->debug(QString("���������������ͷ�: ����=%1, ����=%2")
                .arg(res).arg(rid));
        }
        area->cancelOccupy(rid);
        emit areaReleased(res, rid);
        m_server->respondPost(socket, rspObj);
        return;
    }

    m_server->respondPost(socket, rspObj);
}


} // namespace third_area
} // namespace application
